return ret;
}
+/*
+ * detect pci device, return 0 if it exists, or return 0
+ */
+int pci_device_detect(u8 bus, u8 dev, u8 func)
+{
+ u32 vendor;
+
+ vendor = pci_conf_read32(bus, dev, func, PCI_VENDOR_ID);
+ /* some broken boards return 0 or ~0 if a slot is empty: */
+ if ( (vendor == 0xffffffff) || (vendor == 0x00000000) ||
+ (vendor == 0x0000ffff) || (vendor == 0xffff0000) )
+ return 0;
+ return 1;
+}
+
/*
* scan pci devices to add all existed PCI devices to alldevs_list,
* and setup pci hierarchy in array bus2bridge. This function is only
int bus, dev, func;
u8 sec_bus, sub_bus;
int type;
- u32 l;
spin_lock(&pcidevs_lock);
for ( bus = 0; bus < 256; bus++ )
{
for ( func = 0; func < 8; func++ )
{
- l = pci_conf_read32(bus, dev, func, PCI_VENDOR_ID);
- /* some broken boards return 0 or ~0 if a slot is empty: */
- if ( (l == 0xffffffff) || (l == 0x00000000) ||
- (l == 0x0000ffff) || (l == 0xffff0000) )
+ if ( pci_device_detect(bus, dev, func) == 0 )
continue;
pdev = alloc_pdev(bus, PCI_DEVFN(dev, func));
u64 base_addr = rmrr->base_address, end_addr = rmrr->end_address;
int ret = 0;
- if ( base_addr >= end_addr )
- {
- dprintk(XENLOG_ERR VTDPREFIX,
- "RMRR error: base_addr %"PRIx64" end_address %"PRIx64"\n",
- base_addr, end_addr);
- return -EFAULT;
- }
-
#ifdef CONFIG_X86
/* This check is here simply to detect when RMRR values are
* not properly represented in the system memory map and
rmrru->base_address = base_addr;
rmrru->end_address = end_addr;
- dprintk(XENLOG_INFO VTDPREFIX,
- " RMRR region: base_addr %"PRIx64" end_address %"PRIx64"\n",
- rmrru->base_address, rmrru->end_address);
dev_scope_start = (void *)(rmrr + 1);
dev_scope_end = ((void *)rmrr) + header->length;
if ( ret || (rmrru->scope.devices_cnt == 0) )
xfree(rmrru);
else
- acpi_register_rmrr_unit(rmrru);
+ {
+ u8 b, d, f;
+ int i, ignore = 0;
+
+ for ( i = 0; i < rmrru->scope.devices_cnt; i++ )
+ {
+ b = PCI_BUS(rmrru->scope.devices[i]);
+ d = PCI_SLOT(rmrru->scope.devices[i]);
+ f = PCI_FUNC(rmrru->scope.devices[i]);
+
+ if ( pci_device_detect(b, d, f) == 0 )
+ ignore = 1;
+ else
+ {
+ ignore = 0;
+ break;
+ }
+ }
+
+ if ( ignore )
+ {
+ dprintk(XENLOG_WARNING VTDPREFIX,
+ " Ignore the RMRR (%"PRIx64", %"PRIx64") due to "
+ "devices under its scope are not PCI discoverable!\n",
+ rmrru->base_address, rmrru->end_address);
+ xfree(rmrru);
+ }
+ else if ( base_addr > end_addr )
+ {
+ dprintk(XENLOG_WARNING VTDPREFIX,
+ " The RMRR (%"PRIx64", %"PRIx64") is incorrect!\n",
+ rmrru->base_address, rmrru->end_address);
+ xfree(rmrru);
+ ret = -EFAULT;
+ }
+ else
+ {
+ dprintk(XENLOG_INFO VTDPREFIX,
+ " RMRR region: base_addr %"PRIx64" end_address %"PRIx64"\n",
+ rmrru->base_address, rmrru->end_address);
+ acpi_register_rmrr_unit(rmrru);
+ }
+ }
+
return ret;
}